/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.xsengine;

import java.sql.PreparedStatement;
import com.xsengine.db.DBOperator;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.faces.model.SelectItem;

/**
 *
 * @author baga
 */
public class SearchSystem {

    private String contextString;
    private String[] allDocs;
    private String[] result;
    private double time;
    private boolean isPrepocessing = false;
    private SearchResult[] resultSearch;
    private int testCase = 0;
    private static SelectItem[] testItems = new SelectItem[]{
        new SelectItem(new Integer(0), "TF"),
        new SelectItem(new Integer(1), "IDF"),
        new SelectItem(new Integer(2), "TF IDF")
    };
    private ArrayList documentAll = null;
    private ArrayList valAll = null;
    private Double[] fullVal = null;
    private String[] fullDoc;

    public SearchSystem() {
        documentAll = new ArrayList();
        valAll = new ArrayList();
    }

    public SelectItem[] getTestItems() {
        return testItems;
    }

    public void setContextQuery(String contextQuery) {
        contextString = contextQuery;
    }

    public String getContextQuery() {
        return contextString;
    }

    public int getTestCase() {
        return testCase;
    }

    public void setTestCase(int test) {
        testCase = test;
    }

    /*
     * fungsi ini pengngganti fungsi getSummary. Fungsi ini mengurangi
     * penggunaan HashMap sebagai alat utamanya
     */
    public String getSummNoHM() {
        time = System.currentTimeMillis();
        String table = "dic_post";
        StringBuffer sb = new StringBuffer();
        DBOperator dbOp = new DBOperator();
        StringBuilder sbs = new StringBuilder();
        ArrayList allStop = null;
//        ArrayList allStop = dbOp.stopWords();
        String[] allNormalToken = SplitNormalizeToken.getNormalTokens(contextString);

//        contextString = sbs.toString().trim();
//        allNormalToken = SplitNormalizeToken.getNormalTokens(contextString);


        if (isPrepocessing) {
            table = "dic_post_stem";
        }


        if (isPrepocessing) {
//            table = "words_count_stem";
            allStop = dbOp.stopWords("stopwords");
            for (int i = 0; i < allNormalToken.length; i++) {
                if (!allStop.contains(allNormalToken[i])) {
                    sbs.append(allNormalToken[i] + " ");
                }
            }

            contextString = new String(sbs);
            contextString = contextString.trim();
            allNormalToken = SplitNormalizeToken.getNormalTokensStemmer(contextString);
        }
        for (int i = 0; i < allNormalToken.length; i++) {
            sbs.append(allNormalToken[i] + " ");
        }
        contextString = new String(sbs);
        contextString = contextString.trim();
        allDocs = dbOp.getAllDoc(table, contextString);
//        System.out.println("hasil stoplist " + contextString);
        dbOp.closeConn();
        WeightContext wc = new WeightContext(table);
        ContextResemblance cr = new ContextResemblance();
        Normalizer nm = new Normalizer(table);
        ArrayList<SearchResult> arrResult = new ArrayList<SearchResult>();
        String[] allCtxCr = cr.getStrCR(contextString, allDocs);
//        for (String tempStr : allCtxCr) {
//            System.out.println(tempStr);
//        }
        if (allCtxCr != null && allCtxCr.length > 0) {
            Double[] allCr = cr.getCRVal();
            String temp = "";
            String[] tempArr = null;
            int idx = 0;
            double val = 0.0;
//            HashMap tmpHashMap = new HashMap();
            ArrayList<Double> rankValu = new ArrayList<Double>();
            ArrayList<String> rankStr = new ArrayList<String>();
            StringBuffer strBuf = new StringBuffer();
            for (int i = 0; i < allCr.length; i++) {
                double[] tfidVal = wc.getTfIdfNoHash(allCtxCr[i], testCase);
                double weightQ = wc.getTFQ2(contextString, allCtxCr[i]);

                String[] docs = wc.getDocTFD();
                for (int id = 0; id < tfidVal.length; id++) {
                    tfidVal[id] *= weightQ * allCr[i];  // the value of weight
                    strBuf.append(docs[id].substring(0, docs[id].indexOf("#")) + "~");
                    strBuf.append(allCtxCr[i].substring(0, allCtxCr[i].indexOf("#")) + "[");
                    strBuf.append(allCtxCr[i].substring(allCtxCr[i].lastIndexOf("#") + 1) + "]");
                    temp = strBuf.toString();
                    strBuf.delete(0, strBuf.length());
                    if (!rankStr.contains(temp)) {
                        rankStr.add(temp);
                        rankValu.add(tfidVal[id]);
                    } else {
                        idx = rankStr.indexOf(temp);
                        val = rankValu.get(idx);
                        val += tfidVal[id];
                        rankValu.set(idx, val);
                    }
                }
            }

            Double[] arrDouble = rankValu.toArray(new Double[rankValu.size()]);
            result = rankStr.toArray(new String[rankStr.size()]);

            for (int x = 0; x < arrDouble.length; x++) {
                double max = arrDouble[x];
                int low = x;
                for (int j = x + 1; j < arrDouble.length; j++) {
                    if (max < arrDouble[j]) {
                        low = j;
                        max = arrDouble[j];
                    }
                }
                val = arrDouble[x];
                temp = result[x];
                arrDouble[x] = arrDouble[low];
                arrDouble[low] = val;
                result[x] = result[low];
                result[low] = temp;
            }
//            Arrays.sort(result, Collections.reverseOrder());

            int indexKey = 0;
            double rankValue = 0.0;
            for (int i = 0; i < result.length; i++) {
                String document = result[i].substring(0, result[i].indexOf("~"));
                String sortString = document.substring(document.lastIndexOf("/"));
                String url = "./samples" + sortString;
                String ctx = result[i].substring(result[i].indexOf("~") + 1);
                if (documentAll.isEmpty() || !documentAll.contains(sortString)) {
                    documentAll.add(sortString);
                    valAll.add(arrDouble[i]);
                } else {
                    indexKey = documentAll.indexOf(sortString);
                    rankValue = (Double) valAll.get(indexKey);
                    rankValue += arrDouble[i];
                    valAll.set(indexKey, rankValue);
                }
                //System.out.println(document);
//                arrResult.add(new SearchResult(sortString, url, ctx, getNodesValues(document, ctx), arrDouble[i]));
                arrResult.add(new SearchResult(sortString, url, ctx, getNodesValues(document, ctx), arrDouble[i]));
                strBuf.delete(0, strBuf.length());
            }

//            for (String tmpS : result) {
//                String document = tmpS.substring(0, tmpS.indexOf("~"));
//                String sortString = document.substring(document.lastIndexOf("/"));
//                String url = "./samples" + sortString;
//                String ctx = tmpS.substring(tmpS.indexOf("~") + 1);
//                //System.out.println(document);
//                arrResult.add(new SearchResult(sortString, url, ctx, getNodesValues(document, ctx)));
//                strBuf.delete(0, strBuf.length());
//            }
        } else {
            arrResult.add(new SearchResult("", "", "data tidak ditemukan", "", 0.0));
        }
        //time = (System.currentTimeMillis() - time) / 1000;
        String doksss;
        double valuess;
        String temp;
        Double[] arrDouble = (Double[]) valAll.toArray(new Double[valAll.size()]);
        String[] results = (String[]) documentAll.toArray(new String[documentAll.size()]);
        for (int x = 0; x < arrDouble.length; x++) {
            double max = arrDouble[x];
            int low = x;
            for (int j = x + 1; j < arrDouble.length; j++) {
                if (max < arrDouble[j]) {
                    low = j;
                    max = arrDouble[j];
                }
            }
            valuess = arrDouble[x];
            temp = results[x];
            arrDouble[x] = arrDouble[low];
            arrDouble[low] = valuess;
            results[x] = results[low];
            results[low] = temp;
        }
        fullVal = arrDouble;
        fullDoc = results;

        time = System.currentTimeMillis() - time;
        resultSearch = (SearchResult[]) arrResult.toArray(new SearchResult[arrResult.size()]);
        return "search";
        // must construct for the web
    }

    public String[] getFullDoc() {
        return fullDoc;
    }

    public Double[] getFullVal() {
        return fullVal;
    }

    public SearchResult[] getResult() {
        return resultSearch;
    }

    public double getTimes() {
        return time;
    }

    public boolean getPrepocessing() {
        return isPrepocessing;
    }

    /*
     * fungsi ini bertujuan untuk mengambil data dari xml dengan menggunakan
     * xpath
     * input :
     * (String document, String xpath)
     * output :
     * String
     */
    private String getNodesValues(String docs, String path) {
        String temp = null;
        String countPath = path.substring(path.indexOf("[") + 1, path.length() - 1);
        String tempDoc = docs + "#" + countPath;
//        System.out.println("isi " + tempDoc);
        try {
            String url = "jdbc:mysql://localhost:3306/xsedb";
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection(url,
                    "root", "root");
            PreparedStatement ps = conn.prepareStatement("select content from "
                    + "doc_content where doc = ?");
            ps.setString(1, tempDoc);
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                temp = rs.getString(1);
            }
            ps.clearParameters();
            conn.close();
            conn = null;
            ps = null;
        } catch (ClassNotFoundException ce) {
            ce.printStackTrace();
        } catch (SQLException se) {
            se.printStackTrace();
        }
        return temp;
    }

    public static void main(String[] args) {
        String[] strQuery = {
            "What problems and concerns are there in making up descriptive titles? What difficulties are involved in automatically retrieving articles from approximate titles? What is the usual relevance of the content of articles to their titles?",
            "How can actually pertinent data, as opposed to references or entire articles themselves, be retrieved automatically in response to information requests?",
            "What is information science? Give definitions where possible.",
            "Image recognition and any other methods of automatically transforming printed text into computer-ready form.",
            "What special training will ordinary researchers and businessmen need for proper information management and unobstructed use of information retrieval systems? What problems are they likely to encounter?",
            "What possibilities are there for verbal communication between computers and humans, that is, communication via the spoken word?",
            "Describe presently working and planned systems for publishing and printing original papers by computer, and then saving the byproduct, articles coded in data-processing form, for further use in retrieval.",
            "Describe information retrieval and indexing in other languages. What bearing does it have on the science in general?",
            "What possibilities are there for automatic grammatical and contextual analysis of articles for inclusion in an information retrieval system?",
            "The use of abstract mathematics in information retrieval, e.g. group theory.",
            "What is the need for information consolidation, evaluation, and retrieval in scientific research?",
            "Give methods for high speed publication, printing, and distribution of scientific journals.",
            "What criteria have been developed for the objective evaluation of information retrieval and dissemination systems?",
            "What future is there for automatic medical diagnosis?",
            "How much do information retrieval and dissemination systems, as well as automated libraries, cost? Are they worth it to the researcher and to industry?",
            "What systems incorporate multiprogramming or remote stations in information retrieval? What will be the extent of their use in the future?",
            "Means of obtaining large volume, high speed, customer usable information retrieval output.",
            "What methods are there for encoding, automatically matching, and automatically drawing structures extended in two dimensions, like the structural formulas for chemical compounds?",
            "Techniques of machine matching and machine searching systems. Coding and matching methods.",
            "Testing automated information systems.",
            "The need to provide personnel for the information field.",
            "Automated information in the medical field.",
            "Amount of use of books in libraries. Relation to need for automated information systems.",
            "Educational and training requirements for personnel in the information field. Possibilities for this training. Needs for programs providing this training.",
            "International systems for exchange and dissemination of information.",
            "Cost and determination of cost associated with systems of automated information.",
            "Computerized information retrieval systems. Computerized indexing systems.",
            "Computerized information systems in fields related to chemistry.",
            "Specific advantages of computerized index systems.",
            "Information dissemination by journals and periodicals.",
            "Information systems in the physical sciences.",
            "Attempts at computerized and mechanized systems for general libraries. Problems and methods of automated general author and title indexing systems.",
            "Retrieval systems which provide for the automated transmission of information to the user from a distance.",
            "Methods of coding used in computerized index systems.",
            "Government supported agencies and projects dealing with information dissemination."
        };
        SearchSystem ss = new SearchSystem();
        for (int j = 0; j < strQuery.length; j++) {
            ss.setContextQuery(strQuery[j]);
//        ss.setContextQuery("What possibilities are there for verbal communication between computers and humans, that is, communication via the spoken word?");
            String sq = ss.getContextQuery();

            ArrayList relDoc = RelevantDoc.getRelevantJudgemnet(sq);
            String abc = ss.getSummNoHM();
            Double[] arrDouble = ss.getFullVal();
            String[] results = ss.getFullDoc();

            // write all result to document
            StringBuilder sb = new StringBuilder();
            sb.append("hasi_query_");
            sb.append(RelevantDoc.getQueryNo(sq));
            sb.append("_");
            switch (ss.getTestCase()) {
                case 0:
                    sb.append("tf");
                    break;
                case 1:
                    sb.append("idf");
                    break;
                case 2:
                    sb.append("tfidf");
                    break;
            }
            sb.append("_");
            if (ss.getPrepocessing()) {
                sb.append("prep");
            } else {
                sb.append("noprep");
            }
            sb.append(".txt");
            try {
                PrintWriter out = new PrintWriter(new String(sb));

                System.out.println("<=====================================================================>");
                out.print("<=====================================================================>\n");
                System.out.println("                    START FULL DOCUMENT RESULT                         ");
                out.print("                    START FULL DOCUMENT RESULT                         \n");
                int count = (arrDouble.length > 30 ? 30 : arrDouble.length);
//            for (int i = 0; i < relDoc.size(); i++) {
//                System.out.println("nilai relevan " + relDoc.get(i));
//                out.print("nilai relevan " + relDoc.get(i) + "\n");
//            }
                double rel = 0;
                for (int c = 0; c < count; c++) {
                    if (relDoc.contains(results[c])) {
                        ++rel;
                    }
                    System.out.println("dokumen " + results[c] + " nilainya " + arrDouble[c]);
                    out.print("dokumen " + results[c] + " nilainya " + arrDouble[c] + "\n");
                }
                System.out.println("                      END FULL DOCUMENT RESULT                         ");
                out.write("                      END FULL DOCUMENT RESULT                         \n");
                System.out.println("<=====================================================================>");
                out.print("<=====================================================================>\n");
                System.out.println("<=====================================================================>");
                out.print("<=====================================================================>\n");
                System.out.println("                      START PRECISION & RECALL                         ");
                out.print("                      START PRECISION & RECALL                         \n");
                System.out.println("precision " + (rel / 20.0) + " recall " + (rel / (relDoc.size() * 1.0)));
                out.print("precision " + (rel / 20.0) + " recall " + (rel / (relDoc.size() * 1.0)) + "\n");
                System.out.println("                        END PRECISION & RECALL                         ");
                out.print("                        END PRECISION & RECALL                         \n");
                System.out.println("<=====================================================================>");
                out.print("<=====================================================================>\n");
                SearchResult[] testResult = ss.getResult();
                System.out.println("<=====================================================================>");
                out.print("<=====================================================================>\n");
                System.out.println("                  START DOCUMENT ELEMEN RESULT                         ");
                out.print("                  START DOCUMENT ELEMEN RESULT                         \n");
                for (int i = 0; i < testResult.length; i++) {
                    System.out.println(testResult[i].getDocuments() + " nilai dokumen " + testResult[i].getSimVal());
                    out.print(testResult[i].getDocuments() + " nilai dokumen " + testResult[i].getSimVal() + "\n");
                }
                System.out.println("                    END DOCUMENT ELEMEN RESULT                         ");
                out.print("                    END DOCUMENT ELEMEN RESULT                         \n");
                System.out.println("<=====================================================================>");
                out.print("<=====================================================================>\n");
                out.close();
            } catch (IOException ie) {
                ie.printStackTrace();
            }
        }
    }
}
